// pwr.ixx
module; // 全局模块片段用于包含C头文件

// ================== 包含头文件 ====================
#include <project_config.h>
#include <stm32f4xx_hal.h>
// ================== 包含头文件结束 =================

export module pwr;  // 声明模块接口

// 引入模块依赖
#include <cstdint>

namespace bsp::pwr::detail {
    // PVD配置参数（inline确保常量唯一性）
    inline  PWR_PVDTypeDef pvd_config = {
        .PVDLevel = PWR_PVDLEVEL_7,  // 约2.9V触发
        .Mode = PWR_PVD_MODE_IT_RISING_FALLING
    };

    // 电源控制寄存器操作封装
    namespace reg {
        constexpr uint32_t CR_PDDS    = PWR_CR_PDDS;  // 深度睡眠模式选择位
        constexpr uint32_t CR_CWUF    = PWR_CR_CWUF;  // 清除唤醒标志位
        constexpr uint32_t APB1ENR_EN = RCC_APB1ENR_PWREN; // PWR时钟使能位
    }
}

export namespace bsp::pwr {
    /**
     * @brief 电源管理控制器
     * @note 封装电源管理相关操作，遵循RAII原则
     */
    class Controller {
        // 通用时钟使能
        static void enable_clock() noexcept {
            __HAL_RCC_PWR_CLK_ENABLE();
        }

    public:
        /**
         * @brief 初始化可编程电压检测器(PVD)
         * @details 配置电压阈值为2.9V，上升沿和下降沿触发中断
         * @note 中断优先级设为0（最高），需在project_config.h配置相关时钟
         */
        static void init_pvd() noexcept {
            using namespace detail;

            enable_clock();
            HAL_PWR_ConfigPVD(&pvd_config);

            HAL_PWR_EnablePVD();
            HAL_NVIC_SetPriority(PVD_IRQn, 0, 0);
            HAL_NVIC_EnableIRQ(PVD_IRQn);
        }

        /**
         * @brief 电源模式初始化
         * @details 使能PWR模块时钟，为低功耗模式配置做准备
         */
        static void init_power_mode() noexcept {
            using namespace detail::reg;
            RCC->APB1ENR |= APB1ENR_EN;
        }

        /**
         * @brief 进入睡眠模式
         * @details 通过WFI指令进入，任何中断均可唤醒
         * @note 内核停止，外设保持运行，唤醒后程序继续执行
         */
        static void enter_sleep_mode() noexcept {
            __WFI();  // 等待中断唤醒
        }

        /**
         * @brief 进入停止模式
         * @details 配置PDDS位并清除唤醒标志后进入
         * @note 所有时钟停止，SRAM和寄存器保留，需外部中断或RTC唤醒
         */
        static void enter_stop_mode() noexcept {
            using namespace detail::reg;
            PWR->CR |= CR_PDDS;    // 设置深度睡眠模式
            PWR->CR |= CR_CWUF;    // 清除唤醒标志
            __WFI();               // 进入停止模式
        }

        /**
         * @brief 进入待机模式
         * @details 配置PDDS位并清除唤醒标志后进入
         * @note 仅备份寄存器和待机电路保持供电，需复位或WKUP引脚唤醒
         */
        static void enter_standby_mode() noexcept {
            using namespace detail::reg;
            PWR->CR |= CR_PDDS;    // 设置深度睡眠模式
            PWR->CR |= CR_CWUF;    // 清除唤醒标志
            __WFI();               // 进入待机模式
        }
    };
}

// ================== 中断处理相关 ==================
/**
 * @brief PVD电压检测中断服务函数
 * @warning 必须保持C链接规范
 */
extern "C" void PVD_IRQHandler() {
    HAL_PWR_PVD_IRQHandler();  // 调用HAL库中断处理
}

